/***************************************************************************************************
  Copyright(C)   2011-9-13
  All rights reserved.
  File Name: serialport.h

  Description:串口数据处理模块

    开启一个串口线程来定时接收数据，然后将收到数据存放到缓冲区中，根据收到不同的数据进行处理，
        或者将不同的数据对应不同的串口发送出去

    LCD屏通信协议文档：MTRC SLCD RS-485 Interface specification (SHSI Rev01).pdf
    感光器通信协议文档：Photo Sensor.doc
    SLCD间通信协议文档：H146 Software Design Document_rev2.pdf　6.6章节
  ***************************************************************************************************/
#ifndef SERIALPORT_H
#define SERIALPORT_H

#include <QObject>
#include <QByteArray>
#include <QStringList>
#include <list>

#include "configclass.h"
#include "qextserialthread.h"
#include "qextserialbase.h"

#include "log.h"

#define SLCD_LOG_MAX_SERIBYTE_SIZE  200     //串口收到数据写入日志文件最大数

//LCD回复数据最小数
#define LCD_REPLY_DATA_MINIMUM    14
#define LCD_REPLY_DATA_MAXIMUM    17

//
#define SENSOR_REPLY_DATA_MAXIMUM  5

#define SYNC_REPLY_DATA_MAXIMUM    21

#define IS_PRINT_ERR_DATA_TO_LOG

#define BACKLIGHTLIMMIT 31
typedef enum {
    SENSOR,
    OTHRE,
}TYPEENUM;



typedef struct{
    unsigned char    length[2];         //命令长度
    quint8           sendMode;          //发送方式，广播或者单播
    unsigned char    address[2];        //地址；
    quint16          cmd;               //命令
    QList<unsigned char>    valueList;         //可变的值
    quint8           checkSum;
    quint8           inCheckSum;
} LcdSendStruct;

typedef struct{
    quint16          length;            //命令长度
    quint8           sendMode;          //发送方式，广播或者单播
    quint16          address;           //地址；
    quint16          cmd;               //命令
    quint8           valueCmd;          //variable cmd
    quint8           blStatus;
    quint16          value1;
    quint16          value2;
    quint8           checkSum;
    quint8           inCheckSum;
    quint32          videoStatus;
} LcdReplayStruct;

typedef struct{
    quint8      cmd;
    quint16     brightness;
    quint8      blStatus;
    quint16     panelID;
    quint32     videoStatus;
} LcdReplay;


//interface with adjacent Display Controller in the same car
//  Char No.	Description
//  0               STX 0xFF
//  1               Enquiry Number
//                  (0 ~ 255, each enquiry has number individual number, once the enquiry
//                   number is accumulated to 255, the next enquiry number will be started from 0)
//  2               Type of Displayer Controller
//                  0x00 – Slave; 0x01 – Master
//  3               Year: 0x00 = 2000; 0x43 = 2099;
//  4               Month: 0x01 = 1; 0x0C = 12;
//  5               Day: 0x01 = 1; 0x1F = 31;
//  6               Hour: 0x00 = 0; 0x17 = 23;
//  7               Minute: 0x00 = 0; 0x3B = 59;
//  8               Second: 0x00 = 0; 0x3B = 59
//  9               Brightness
//  10-17           Reserved
//  18              EXT 0xFE
//  19-20           Check Sum

typedef struct{
    qint8 stx;
    qint8 enquiryNum;    //询问码
    qint8 typeDev;       //设备类型(主次之分，0x00-salve; 0x01-master)
    qint8 year;          //0x00:2000; 0x43:2099
    qint8 month;         //0x01:1; 0x0c:12
    qint8 day;           //0x01:1; 0x1f:31
    qint8 hour;          //0x00:0; 0x17:23
    qint8 minute;        //0x00:0; 0x3B:59
    qint8 second;        //0x00:0; 0x3B:59
    qint8 brightness;
    qint64 reserved;     //保留位
    qint8 ext;
    qint16 checkSum;
} SynchCommand;

//是否输出错误数据到日记文件
//#define IS_PRINT_ERR_DATA_TO_LOG

extern Debug_Config_s g_stDebugConfig;

class QextSerialThread;

class SerialPort : public QObject
{
    Q_OBJECT
    LOG4QT_DECLARE_QCLASS_LOGGER

public:
    explicit SerialPort(int type = 0, QObject *parent = 0);
    //type串口类型（0：接收环境光度感应；1，SLCD显示屏控制 3,displayer之间的通信）

    ~SerialPort();

    bool openSeriPort(QIODevice::OpenMode openMode);
    void cloesSeriPort();

    void setPanelInfoIDList(const QList<PanelInfoStruct> infoList);

    bool isOpen() const;
    bool isReadable() const;
    bool isWritable() const;

    void setDefaultPortSetting();

    int bytesAvailable();
    QByteArray readAll();
    int write(QByteArray sendBytes);
    void sendData(int sendType, QByteArray data);

    void setPort(const QString& port);
    void setBaudRate(BaudRateType);
    void setDataBits(DataBitsType);
    void setParity(ParityType);
    void setStopBits(StopBitsType);
    void setFlowControl(FlowType);
    void setTimeout(long);
    void setDtr(bool set=true);
    void setRts(bool set=true);

    void setReadTime(int timeSize);
    void setPortSettings(PortSettings portSettings);
    void closeThread();

    inline void selectPanel(qint16 panelID);
    void bcastCtlbrightness(qint16 brightness);
    void ctlBrightness(qint16 panelID, qint16 brightness);
//    void brightnessCtl(qint16 brightness);

    void bcastIncrementBL();         //increment bcaklight
    void incrementBL(qint16 panelID);

    void bcastDecrementBL();         //decrement backlight
    void decrementBL(qint16 panelID);

    void bcastResetBL();
    void resetBL(qint16 panleID);

    void bcastCtlBLStatu(quint8 cmd);
    void ctlBLStatu(qint16 panelID, quint8 cmd);

    quint8 queryVideoStatus(qint16 panelID);
    void setSendIsAscii(const bool flag);

signals:
    void readReay();
    void sentBytes(QByteArray sendBytes);
    void closeTheadSignal();
    void receSensorData(qint16 brightness);

    //lcd回复亮度设置
    void lcdReplyBrightness(const LcdReplay &lcdReply);

    //lcd回复背景灯状态
    void lcdReplyBLStatus(const LcdReplay &lcdReply);

    //lcd回复恢复默认设置
    void lcdReplyReset(const LcdReplay &lcdReply);

    //lcd回复查询LCD屏状态
    void lcdReplyVideoStatu(const LcdReplay &lcdReply);

    void receSyncCommand(const SynchCommand& synCommand);

//    void receBrightnessStatus(quint8 Status);
//    void receBackLightStatus(quint8 Status);
//    void receVideoStatus(qint16 status);

private:
    QextSerialThread *qextSerialThread;             //定时读取串口数据的线程
    PortSettings mPortSettings;                     //串口的基本设置结构体
    int mTimeSize;                                  //读取串口数据间隔时间
    QString mPort;                                  //串口名


    QList<PanelInfoStruct> m_panelInfoList;                        //lcd info列表

    ////串口收到的数据，将每一次收到的数据都存贮在此缓冲区中，等到了一定的数量再进行处理
    QByteArray mReceBytes;

    int serialType;             //串口类型（0：接收环境光度感应；1，LCD显示屏控制）
    TYPEENUM typeEnum;
    bool portIsOpen;
    bool sendIsAscii;           //是否发送的为ascii码值

private:
    void init();
    quint8 sendLcdCmd(const LcdSendStruct& lcdSendStruct);
    void countCheckSum(LcdSendStruct& lcdSendStruct);


    QByteArray processSensorData(const QByteArray& bytes);
    QByteArray processLcdReply(const QByteArray& bytes);
    QByteArray processSynchCommand(const QByteArray& bytes);



public slots:
    void receBytes(QByteArray receBytes);
    void sendSynchCommand(const SynchCommand& synCommand);
};

#endif // SERIALPORT_H
